//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V0.2.4
#include "debug_driver.h"

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "../../Tool/Ring_Buffer/Ring_Buffer.h"
#include "../../Tool/Ring_Queue/Ring_Queue.h"

static uint8_t WHT_Tx_Buffer[DEBUG_Max_Buffer_Size];//串口底层发送缓存
static uint8_t WHT_Rx_Buffer[DEBUG_Max_Buffer_Size];//串口底层接收缓存

static WHT_Ring_Buffer_Handle_t Debug_Tx_Ring_Buffer;
static WHT_Ring_Queue_Handle_t Debug_Rx_Ring_Queue;

static WHT_UART_Cache_t wht_cache;

static TaskHandle_t WHT_Task_Handle;   //任务句柄
static SemaphoreHandle_t Tx_xSemaphore;//二值信号量句柄
static SemaphoreHandle_t Rx_xSemaphore;



/*Debug发送空闲中断回调函数*/
static void WHT_Debug_Driver_Tx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(Tx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
/*Debug接收空闲中断回调函数*/
static void WHT_Debug_Driver_Rx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    WHT_Ring_Queue.WHT_Write(Debug_Rx_Ring_Queue, wht_cache.Rx_Buf, wht_cache.Rx_Count);//留意写入失败，特别是互斥锁导致
    //WHT_UART_BSP.WHT_Interrupt_Receive(&wht_cache);
    WHT_UART_BSP.WHT_DMA_Receive(&wht_cache);
    xSemaphoreGiveFromISR(Rx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
/*Debug发送FIFO数据*/
static void WHT_Debug_Driver_Send_Buf(const uint8_t* tx_buf, uint32_t send_length)
{
    //等待发送完成
    while (wht_cache.Info->Tx_State != UART_Tx_Idle)   
        vTaskDelay(1);
    wht_cache.Tx_Count = send_length;
    wht_cache.Tx_Buf = (uint8_t*)tx_buf;
    
    TickType_t Tick_Count = send_length * 10 * 1000  / DEBUG_Serial_Baud_Rate;///单位ms
    if (Tick_Count >=  portTICK_RATE_MS)
        WHT_UART_BSP.WHT_DMA_Send(&wht_cache);
    else
        WHT_UART_BSP.WHT_Interrupt_Send(&wht_cache);
}

/*Debug调试任务*/
static void WHT_Deubg_Task(void* parameter)
{
    Tx_xSemaphore = xSemaphoreCreateBinary();
    Rx_xSemaphore = xSemaphoreCreateBinary();

    PRINT_INFO("My name is WangHaitao\r\n");
    for (; ;)
    {
        /*判断是否有需要发送的数据*/
        if (WHT_Ring_Buffer.WHT_Get_Data_Size(Debug_Tx_Ring_Buffer))
        {
            uint16_t length = WHT_Ring_Buffer.WHT_Read(Debug_Tx_Ring_Buffer, WHT_Tx_Buffer, sizeof(WHT_Tx_Buffer));
            WHT_Debug_Driver_Send_Buf(WHT_Tx_Buffer, length);
            xSemaphoreTake(Tx_xSemaphore, portMAX_DELAY);//等待信号量
        }
        else
        {
            vTaskSuspend(NULL);
        }
    }
}


/*Debug发送数据*/
static void WHT_Printf(const char* tx_buf, uint16_t send_length)
{
    uint16_t Length = 0;

    do
    {
        tx_buf += Length;
        send_length -= Length;
        Length = WHT_Ring_Buffer.WHT_Write(Debug_Tx_Ring_Buffer, (const uint8_t*)tx_buf, send_length);
        vTaskResume(WHT_Task_Handle);//恢复任务运行
        if (Length == send_length)
            break;
        else
            vTaskDelay(1);
    } while (1);
}
/*Debug获取接收状态和数据*/
static uint16_t WHT_Scanf(uint8_t* rx_buf, uint16_t max_receive_length, uint32_t timeout)
{
    if (WHT_Ring_Queue.WHT_Get_Empty_State(Debug_Rx_Ring_Queue) == 0)
    {
        if (xSemaphoreTake(Rx_xSemaphore, timeout/portTICK_RATE_MS) == pdFALSE)//等待信号量
            return 0;
    }
    return WHT_Ring_Queue.WHT_Read(Debug_Rx_Ring_Queue, rx_buf, max_receive_length);
}
/*Debug初始化注册*/
static void WHT_Debug_Driver_Register(void)
{
    static uint8_t Tx_Ring_Buffer[DEBUG_Max_Buffer_Size];   //发送环形缓冲区
    static uint8_t Rx_Ring_Queue[DEBUG_Max_Buffer_Size * 3];//接收环形队列

    WHT_Ring_Buffer.WHT_Register(&Debug_Tx_Ring_Buffer, Tx_Ring_Buffer, sizeof(Tx_Ring_Buffer));
    WHT_Ring_Queue.WHT_Register(&Debug_Rx_Ring_Queue, Rx_Ring_Queue, sizeof(Rx_Ring_Queue), DEBUG_Max_Queue_Count);

    wht_cache.Rx_Buf_Size = DEBUG_Max_Buffer_Size;
    wht_cache.Rx_Count = 0;
    wht_cache.Rx_Buf = WHT_Rx_Buffer;
    wht_cache.Rx_Idle_IT_Callback = WHT_Debug_Driver_Rx_Idle_IT_Callback;
    wht_cache.Tx_Idle_IT_Callback = WHT_Debug_Driver_Tx_Idle_IT_Callback;

    WHT_UART_Config_t wht_config = WHT_UART_DEFAULT_CONFIG(DEBUG_Serial_Name);
    wht_config.Bps = DEBUG_Serial_Baud_Rate;
    WHT_UART_BSP.WHT_Register(&wht_config, &wht_cache);
    WHT_UART_BSP.WHT_Config(&wht_config, &wht_cache);
    //WHT_UART_BSP.WHT_Interrupt_Receive(&wht_cache);
    WHT_UART_BSP.WHT_DMA_Receive(&wht_cache);
    xTaskCreate(WHT_Deubg_Task, "WHT_Deubg_Task", 256, NULL, configMAX_PRIORITIES, &WHT_Task_Handle);
}


const WHT_Debug_Driver_t WHT_Debug_Driver =
{
    .WHT_Init = WHT_Debug_Driver_Register,
    .WHT_Printf = WHT_Printf,
    .WHT_Scanf = WHT_Scanf,
};





/*Debug阻塞发送*/
static void WHT_Block_Printf(const char* tx_buf, uint32_t send_length)
{
    //等待发送完成
    while (wht_cache.Info->Tx_State != UART_Tx_Idle)
        vTaskDelay(1);
    wht_cache.Tx_Count = send_length;
    wht_cache.Tx_Buf = (uint8_t*)tx_buf;
    WHT_UART_BSP.WHT_Send(&wht_cache);
}

//重定向c库函数printf到串口，重定向后可使用printf函数
int fputc(int ch, FILE* f)
{
    WHT_Block_Printf((char*)&ch, 1);
    return ch;
}
//重定向c库函数scanf到串口，重写向后可使用scanf、getchar等函数
int fgetc(FILE* f)
{
    uint8_t rx_buf[1];

    WHT_Scanf(rx_buf, 1, 1);
    return (int)rx_buf[0];
}
